﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using ManagedService;
using Interfaces;
using System.MessagingCE;

namespace PozrSvc
{
    class ServiceHost : ServiceApplication
    {
        private Middleware Core;
        private MessageDispatcher Dispatcher;

        public ServiceHost()
        {
            this.ServiceGuid = System.Guid.NewGuid();
            this.ServiceName = "PozrSvc";
            Dispatcher = new MessageDispatcher();
            Core = new Middleware();

            Dispatcher.RegisterMessageReader("ApplicationEvent", new EventHandler(ApplicationEventHandler));
            Dispatcher.RegisterMessageReader("SignalEvent", new EventHandler(SignalEventHandler));
            Dispatcher.RegisterMessageReader("MarkerEvent", new EventHandler(MarkerEventHandler));

            Middleware.NewAbsoluteDataAvailableEvent += delegate(object sender, PositionEventArgs data)
            {
                Dispatcher.MultipointSend("NewAbsoluteDataAvailable", new SignalEventMessage(data));
            };
            Middleware.NewCellDataAvailableEvent += delegate(object sender, PositionEventArgs data)
            {
                Dispatcher.MultipointSend("NewCellDataAvailable", new SignalEventMessage(data));
            };

            this.RegisterService();
        }

        private void ApplicationEventHandler(object sender, EventArgs e)
        {
            ApplicationEventMessage msg = new ApplicationEventMessage();
            if (Dispatcher.Receive("ApplicationEvent", msg))
            {
                switch (msg.Args.Op)
                {
                    case ApplicationEventMessage.ApplicationEventArgs.Operation.Attach:
                        Dispatcher.RegisterMessageWriter("NewAbsoluteDataAvailable_" + msg.Args.Guid);
                        Dispatcher.RegisterMessageWriter("NewCellDataAvailable_" + msg.Args.Guid);
                        break;
                    case ApplicationEventMessage.ApplicationEventArgs.Operation.Detach:
                        Dispatcher.RemoveMessagePoint("NewAbsoluteDataAvailable_" + msg.Args.Guid);
                        Dispatcher.RemoveMessagePoint("NewCellDataAvailable_" + msg.Args.Guid);
                        break;
                    default:
                        throw new InvalidOperationException("Invalid Application Operation");
                }
            }
        }

        private void SignalEventHandler(object sender, EventArgs e)
        {
            SignalEventMessage msg = new SignalEventMessage();
            if(Dispatcher.Receive("SignalEvent", msg))
            {
                switch (msg.Args.Op)
                {
                    case PositionEventArgs.Operation.New:
                        Middleware.OnNewSignal(this, msg.Args);
                        break;
                    case PositionEventArgs.Operation.Best:
                        Middleware.OnBestSignal(this, msg.Args);
                        break;
                    default:
                        throw new InvalidOperationException("Invalid Signal Operation");
                }
            }
        }

        private void MarkerEventHandler(object sender, EventArgs e)
        {
            MarkerMessage msg = new MarkerMessage();
            if (Dispatcher.Receive("MarkerEvent", msg))
            {
                switch (msg.Args.Op)
                {
                    case MarkerMessage.MarkerEventArgs.Operation.New:
                        Middleware.Markers.Add(msg.Args.Position.Latitude, msg.Args.Position.Longitude, msg.Args.ProtoId, msg.Args.Text, msg.Args.Image);
                        break;
                    case MarkerMessage.MarkerEventArgs.Operation.Modify:
                        Middleware.Markers.Move(msg.Args.Id, msg.Args.Position.Latitude, msg.Args.Position.Longitude);
                        break;
                    case MarkerMessage.MarkerEventArgs.Operation.Delete:
                        throw new NotImplementedException("Marker.Delete operation not supported yet");
                        break;
                    default:
                        throw new InvalidOperationException("Invalid Marker Operation");
                }
            }
        }
    }
}
